﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DK.StackCalculator.Demo;

public class StackCalculator
{

    Stack<int> numberStack = new Stack<int>();
    Stack<char> charStack = new Stack<char>();

    public int GetExpressionResult(string expression)
    {
        //遍历字符串，数字进入数字栈，运算符进入运算符栈；
        //如果运算符栈为空，直接入栈；
        //栈中有符先对比优先级，优先级比栈内高直接入栈;
        //优先级比栈内小先做栈内运算符的运算,运算后结果再放入数字栈，新运算符入栈；

        foreach (var item in expression)
        {
            string number = "";
            if (IsOper(item))
            {
                if (charStack.Count > 0)
                {
                    if (Priority(charStack.Peek()) >= Priority(item))
                    {
                        var temp = Compute(numberStack.Pop(),numberStack.Pop(),charStack.Pop());
                        numberStack.Push(temp);
                    }
                }
                charStack.Push(item);
            }
            else 
            {
                number += item;
                if (expression.IndexOf(item) == expression.Length - 1 || IsOper(expression[expression.IndexOf(item) + 1])) 
                {
                    numberStack.Push(int.Parse(number));
                    number = "";
                }
            }
        }

        while (charStack.Count > 0 && numberStack.Count > 1)
        {
            var temp = Compute(numberStack.Pop(), numberStack.Pop(), charStack.Pop());
            numberStack.Push(temp);
        }

        return numberStack.Pop();
    }

    public bool IsOper(char oper) 
    {
        return oper == '+' || oper == '-' || oper == '*' || oper == '/';
    }

    public bool IsNumber(char oper) 
    {
        return oper > 48 && oper < 57;
    }

    public int Priority(char oper) 
    {
        if (oper == '*' || oper == '/') return 1;
        else if (oper == '+' || oper == '-') return 0;
        else throw new Exception("invalid character.");
    }

    public int Compute(int n1, int n2, char oper) 
    {
        int value;
        switch (oper)
        {
            case '+':
                value = n2 + n1;
                break;
            case '-': 
                value = n2 - n1; 
                break;
            case '*':
                value = n2 * n1;
                break;
            case '/':
                value = n2 / n1;
                break;
            default:
                throw new Exception("invalid character.");
        }
        return value;
    }
}